﻿using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using EIP.Common.Dapper.Extensions.DBUtility;
using EIP.Common.Entities.CustomAttributes;
namespace EIP.Common.Dapper.Extensions.Common
{
    public class DbEntityUtils
    {
        //获取数据库命名参数符号，比如@(SQLSERVER)、:(ORACLE)
        public static string DbParmChar = DbFactory.CreateDbParmCharacter();

        /// <summary>
        /// 获取表基础信息
        /// </summary>
        /// <param name="classType"></param>
        public static string GetTableName(Type classType)
        {
            string strTableName = string.Empty;
            string strEntityName = classType.FullName;
            var classAttr = classType.GetCustomAttributes(typeof(TableAttribute), false);
            var info = classAttr[0] as TableAttribute;
            if (info != null)
                strTableName = info.Name;
            if (string.IsNullOrEmpty(strTableName))
            {
                throw new Exception("实体类:" + strEntityName + "的属性配置[Table(name=\"tablename\")]错误或未配置");
            }
            return strTableName;
        }

        

        /// <summary>
        /// 获取主键
        /// </summary>
        /// <param name="attribute"></param>
        /// <returns></returns>
        public static string GetPrimaryKey(object attribute)
        {
            string strPrimary = string.Empty;
            IdAttribute attr = attribute as IdAttribute;
            switch (attr.Strategy)
            {
                case GenerationType.Indentity:
                    break;
                case GenerationType.Sequence:
                    strPrimary = Guid.NewGuid().ToString();
                    break;
                case GenerationType.Table:
                    break;
            }
            return strPrimary;
        }

        public static string GetColumnName(object attribute)
        {
            string columnName = string.Empty;
            if (attribute is ColumnAttribute)
            {
                ColumnAttribute columnAttr = attribute as ColumnAttribute;
                columnName = columnAttr.Name;
            }
            if (attribute is IdAttribute)
            {
                IdAttribute idAttr = attribute as IdAttribute;
                columnName = idAttr.Name;
            }

            return columnName;
        }

        /// <summary>
        /// 获取表基础信息
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="dbOpType"></param>
        /// <returns></returns>
        public static TableInfo GetTableInfo(object entity, DbOperateType dbOpType)
        {
            bool breakForeach = false;
            bool isAdd = true;
            string strPrimaryKey = string.Empty;
            TableInfo tableInfo = new TableInfo();
            Type type = entity.GetType();
            tableInfo.TableName = GetTableName(type);
            PropertyInfo[] properties = ReflectionUtils.GetProperties(type);
            foreach (PropertyInfo property in properties)
            {
                object propvalue = null;
                string columnName = string.Empty;
                string propName = columnName = property.Name;
                if (dbOpType != DbOperateType.Select)
                    propvalue = ReflectionUtils.GetPropertyValue(entity, property);

                object[] propertyAttrs = property.GetCustomAttributes(false);
                for (int i = 0; i < propertyAttrs.Length; i++)
                {
                    object propertyAttr = propertyAttrs[i];
                    if (IsCaseColumn(propertyAttr, dbOpType))
                    {
                        breakForeach = true; break;
                    }

                    string tempVal = GetColumnName(propertyAttr);
                    columnName = tempVal == string.Empty ? propName : tempVal;

                    if (propertyAttr is IdAttribute)
                    {
                        if (dbOpType == DbOperateType.Insert)
                        {
                            IdAttribute idAttr = propertyAttr as IdAttribute;
                            tableInfo.Strategy = idAttr.Strategy;

                            if (CommonUtils.IsNullOrEmpty(propvalue))
                            {
                                strPrimaryKey = GetPrimaryKey(propertyAttr);
                                if (!string.IsNullOrEmpty(strPrimaryKey))
                                    propvalue = strPrimaryKey;
                            }
                        }

                        tableInfo.Id.Key = columnName;
                        tableInfo.Id.Value = propvalue;
                        tableInfo.PropToColumn.Put(propName, columnName);
                        breakForeach = true;
                    }
                    if (propertyAttr is ColumnAttribute)
                    {
                        ColumnAttribute columnAttribute = propertyAttr as ColumnAttribute;
                        //不查询
                        if (!columnAttribute.IsSelect)
                        {
                            isAdd = false;
                        }
                        //该字段排序
                        if (columnAttribute.IsSort)
                        {
                            tableInfo.Sort += columnName + " " + columnAttribute.SortType + ",";
                        }
                    }
                }
                if (breakForeach)
                {
                    breakForeach = false;
                    continue;
                }

                else if (!isAdd)
                {
                    isAdd = true;
                    continue;
                }
                else
                {
                    tableInfo.Columns.Put(columnName, propvalue);
                    tableInfo.PropToColumn.Put(propName, columnName);
                }
            }

            return tableInfo;
        }

        /// <summary>
        /// 获取数据日志记录字符串(Json格式)
        /// </summary>
        /// <param name="entity">实体</param>
        /// <returns></returns>
        public static string GetDataLogJson(object entity)
        {
            string json = "["; ;
            Type type = entity.GetType();
            PropertyInfo[] properties = ReflectionUtils.GetProperties(type);
            //反射属性
            foreach (PropertyInfo property in properties)
            {
                json += "{";
                var propvalue = ReflectionUtils.GetPropertyValue(entity, property);
                //得到每个属性特性
                object[] propertyAttrs = property.GetCustomAttributes(false);
                for (int i = 0; i < propertyAttrs.Length; i++)
                {
                    object propertyAttr = propertyAttrs[i];
                    if (propertyAttr is ColumnAttribute)
                    {
                        ColumnAttribute columnAttribute = propertyAttr as ColumnAttribute;
                        json += "\"Key\":\"" + property.Name + "\",\"Value\":\"" + propvalue + "\",\"Description\":\"" + columnAttribute.Description + "\"";
                    }
                }
                json += "},";
            }
            json = json.TrimEnd(',');
            json += "]";
            return json;
        }

        /// <summary>
        /// 查询所有sql语句
        /// </summary>
        /// <param name="tableInfo"></param>
        /// <returns></returns>
        public static string GetFindAllSql(TableInfo tableInfo)
        {
            StringBuilder sbColumns = new StringBuilder();

            tableInfo.Columns.Put(tableInfo.Id.Key, tableInfo.Id.Value);
            foreach (String key in tableInfo.Columns.Keys)
            {
                sbColumns.Append(("[" + key + "]")).Append(",");
            }

            sbColumns.Remove(sbColumns.ToString().Length - 1, 1);

            string strSql = "SELECT {0} FROM [{1}]";
            strSql = string.Format(strSql, sbColumns.ToString(), tableInfo.TableName);
            if (!string.IsNullOrEmpty(tableInfo.Sort))
            {
                strSql += " ORDER BY " + tableInfo.Sort.TrimEnd(',');
            }
            return strSql;
        }

        /// <summary>
        /// 获得查询sql
        /// </summary>
        /// <param name="tableInfo"></param>
        /// <returns></returns>
        public static string GetFindByIdSql(TableInfo tableInfo)
        {
            StringBuilder sbColumns = new StringBuilder();

            if (tableInfo.Columns.ContainsKey(tableInfo.Id.Key))
                tableInfo.Columns[tableInfo.Id.Key] = tableInfo.Id.Value;
            else
                tableInfo.Columns.Put(tableInfo.Id.Key, tableInfo.Id.Value);

            foreach (String key in tableInfo.Columns.Keys)
            {
                sbColumns.Append(("[" + key + "]")).Append(",");
            }

            sbColumns.Remove(sbColumns.ToString().Length - 1, 1);

            string strSql = "SELECT {0} FROM [{1}] WHERE {2} = " + DbParmChar + "Id";
            strSql = string.Format(strSql, sbColumns.ToString(), tableInfo.TableName, tableInfo.Id.Key);

            return strSql;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="tableInfo"></param>
        /// <returns></returns>
        public static string GetFindByPropertySql(TableInfo tableInfo)
        {
            StringBuilder sbColumns = new StringBuilder();

            tableInfo.Columns.Put(tableInfo.Id.Key, tableInfo.Id.Value);
            foreach (String key in tableInfo.Columns.Keys)
            {
                sbColumns.Append(("[" + key + "]")).Append(",");
            }

            sbColumns.Remove(sbColumns.ToString().Length - 1, 1);

            string strSql = "SELECT {0} FROM [{1}] WHERE {2} = " + DbParmChar + "{2}";
            strSql = string.Format(strSql, sbColumns, tableInfo.TableName, tableInfo.Id.Key);

            return strSql;
        }

        /// <summary>
        /// 获取插入sql
        /// </summary>
        /// <param name="tableInfo"></param>
        /// <returns></returns>
        public static string GetInsertSql(TableInfo tableInfo)
        {
            StringBuilder sbColumns = new StringBuilder();
            StringBuilder sbValues = new StringBuilder();

            //判断是否具有主键
            if (tableInfo.Strategy != GenerationType.Indentity)
                if (!string.IsNullOrEmpty(tableInfo.Id.Key))
                {
                    tableInfo.Columns.Put(tableInfo.Id.Key, tableInfo.Id.Value);
                }

            foreach (String key in tableInfo.Columns.Keys)
            {
                if (!string.IsNullOrEmpty(key.Trim()))
                {
                    sbColumns.Append("[" + key + "]").Append(",");
                    sbValues.Append(DbParmChar).Append(key).Append(",");
                }
            }

            sbColumns.Remove(sbColumns.ToString().Length - 1, 1);
            sbValues.Remove(sbValues.ToString().Length - 1, 1);

            string strSql = "INSERT INTO [{0}]({1}) VALUES({2})";
            strSql = string.Format(strSql, tableInfo.TableName, sbColumns, sbValues);

            return strSql;
        }

        /// <summary>
        /// 获取插入sql
        /// </summary>
        /// <param name="tableInfo"></param>
        /// <returns></returns>
        public static string GetInsertScalarSql(TableInfo tableInfo)
        {
            StringBuilder sbColumns = new StringBuilder();
            StringBuilder sbValues = new StringBuilder();

            //判断是否具有主键
            if (tableInfo.Strategy != GenerationType.Indentity)
                if (!string.IsNullOrEmpty(tableInfo.Id.Key))
                {
                    tableInfo.Columns.Put(tableInfo.Id.Key, tableInfo.Id.Value);
                }

            foreach (String key in tableInfo.Columns.Keys)
            {
                if (!string.IsNullOrEmpty(key.Trim()))
                {
                    sbColumns.Append("[" + key + "]").Append(",");
                    sbValues.Append(DbParmChar).Append(key).Append(",");
                }
            }

            sbColumns.Remove(sbColumns.ToString().Length - 1, 1);
            sbValues.Remove(sbValues.ToString().Length - 1, 1);
            string strSql = "INSERT INTO [{0}]({1}) VALUES({2});select @@identity";
            strSql = string.Format(strSql, tableInfo.TableName, sbColumns, sbValues);
            return strSql;
        }

        /// <summary>
        /// 获取更新sql
        /// </summary>
        /// <param name="tableInfo"></param>
        /// <returns></returns>
        public static string GetUpdateSql(TableInfo tableInfo)
        {
            StringBuilder sbBody = new StringBuilder();
            foreach (String key in tableInfo.Columns.Keys)
            {
                sbBody.Append(("[" + key + "]")).Append("=").Append(DbParmChar + key).Append(",");
            }
            sbBody.Remove(sbBody.ToString().Length - 1, 1);
            tableInfo.Columns.Put(tableInfo.Id.Key, tableInfo.Id.Value);
            string strSql = "update [{0}] set {1} where {2} =" + DbParmChar + tableInfo.Id.Key;
            strSql = string.Format(strSql, tableInfo.TableName, sbBody, tableInfo.Id.Key);
            return strSql;
        }

        /// <summary>
        /// 获取删除sql
        /// </summary>
        /// <param name="tableInfo"></param>
        /// <returns></returns>
        public static string GetDeleteByPropertySql(TableInfo tableInfo)
        {
            string strSql = "delete [{0}] where {1} = " + DbParmChar + tableInfo.Id.Key;
            strSql = string.Format(strSql, tableInfo.TableName, tableInfo.Id.Key);
            return strSql;
        }

        public static string GetDeleteByIdSql(TableInfo tableInfo)
        {
            string strSql = "delete [{0}] where {1} = " + DbParmChar + "Id";
            strSql = string.Format(strSql, tableInfo.TableName, tableInfo.Id.Key);
            return strSql;
        }

        /// <summary>
        /// 删除所有
        /// </summary>
        /// <param name="tableInfo"></param>
        /// <returns></returns>
        public static string DeleteAll(TableInfo tableInfo)
        {
            string strSql = "delete [{0}]";
            strSql = string.Format(strSql, tableInfo.TableName);
            return strSql;
        }

        /// <summary>
        ///     获取批量删除语句
        /// </summary>
        /// <param name="tableInfo"></param>
        /// <param name="list"></param>
        /// <returns></returns>
        public static string GetDeleteBatchSql(TableInfo tableInfo, string list)
        {
            string param = "";
            if (!string.IsNullOrEmpty(list))
            {
                var strList = list.Split(',');
                param = strList.Aggregate(param, (current, str) => current + ("'" + str + "',"));
            }
            string strSql = "delete [{0}] where {1} in (" + param.TrimEnd(',') + ")";
            strSql = string.Format(strSql, tableInfo.TableName, tableInfo.Id.Key);
            return strSql;
        }

        /// <summary>
        /// 参数化sql
        /// </summary>
        /// <param name="columns"></param>
        /// <param name="parms"></param>
        public static void SetParameters(ColumnInfo columns, params IDbDataParameter[] parms)
        {
            int i = 0;
            foreach (string key in columns.Keys)
            {
                if (!string.IsNullOrEmpty(key.Trim()))
                {
                    parms[i].ParameterName = key;
                    parms[i].Value = columns[key];
                    i++;
                }
            }
        }

        public static bool IsCaseColumn(object attribute, DbOperateType dbOperateType)
        {
            if (attribute is ColumnAttribute)
            {
                ColumnAttribute columnAttr = attribute as ColumnAttribute;
                if (!columnAttr.IsInsert && dbOperateType == DbOperateType.Insert)
                {
                    return true;
                }
                if (!columnAttr.IsUpdate && dbOperateType == DbOperateType.Update)
                {
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// 获取主键值
        /// </summary>
        /// <param name="entity">实体</param>
        /// <returns></returns>
        public static string GetTableKeyValue(object entity)
        {
            object propvalue = null;
            Type type = entity.GetType();
            PropertyInfo[] properties = ReflectionUtils.GetProperties(type);
            foreach (PropertyInfo property in properties)
            {
                object[] propertyAttrs = property.GetCustomAttributes(false);
                for (int i = 0; i < propertyAttrs.Length; i++)
                {
                    object propertyAttr = propertyAttrs[i];
                    if (propertyAttr is IdAttribute)
                    {
                        propvalue = property.GetValue(entity, null);
                        break;
                    }
                }
            }
            if (propvalue != null)
                return propvalue.ToString();
            return null;
        }
    }
}